package com.huahai.controller;


import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.huahai.annotation.AuthCheck;
import com.huahai.common.BaseResponse;
import com.huahai.common.DeleteRequest;
import com.huahai.constant.UserConstant;
import com.huahai.exception.BusinessException;
import com.huahai.exception.ErrorCode;
import com.huahai.pojo.dto.user.*;
import com.huahai.pojo.entity.User;
import com.huahai.pojo.vo.user.UserLoginVO;
import com.huahai.pojo.vo.user.UserVO;
import com.huahai.service.UserService;
import com.huahai.util.ResultUtils;
import com.huahai.util.ThrowUtils;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 用户controller接口模块
 *
 * @author huahai
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    /**
     * 用户注册
     *
     * @param userRegisterDTO 用户注册信息
     * @return 注册用户id
     */
    @ApiOperation(value = "用户注册")
    @PostMapping("/register")
    public BaseResponse<Long> userRegister(@RequestBody UserRegisterDTO userRegisterDTO) {
        // 参数校验
        if (ObjUtil.isNull(userRegisterDTO)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long userId = userService.userRegister(userRegisterDTO);
        if (userId < 0) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败");
        }
        return ResultUtils.success(userId);
    }

    /**
     * 用户登录
     *
     * @param userLoginDTO 用户注册信息
     * @param request      请求
     * @return 登录用户信息
     */
    @ApiOperation(value = "用户登录")
    @PostMapping("/login")
    public BaseResponse<UserLoginVO> userLogin(@RequestBody UserLoginDTO userLoginDTO, HttpServletRequest request) {
        // 参数校验
        if (ObjUtil.isNull(userLoginDTO)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 登录
        UserLoginVO userLoginVO = userService.userLogin(userLoginDTO, request);
        return ResultUtils.success(userLoginVO);
    }

    /**
     * 获取当前登陆用户信息
     *
     * @param request 请求
     * @return 用户信息
     */
    @ApiOperation(value = "获取当前登陆用户信息")
    @GetMapping("/get/login")
    public BaseResponse<UserLoginVO> getLoginUser(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        UserLoginVO userLoginVO = userService.getUserLoginVO(loginUser);
        return ResultUtils.success(userLoginVO);
    }

    /**
     *
     * 用户登出
     * @param request 请求
     * @return 登出结果
     */
    @ApiOperation(value = "用户登出")
    @PostMapping("/logout")
    public BaseResponse<Boolean> userLogout(HttpServletRequest request) {
        ThrowUtils.throwIf(request == null, ErrorCode.PARAMS_ERROR);
        boolean result = userService.userLogout(request);
        return ResultUtils.success(result);
    }

    /**
     * 新增用户 （管理员）
     *
     * @param userAddDTO 新增用户参数
     * @return 新增用户id
     */
    @ApiOperation(value = "新增用户（管理员）")
    @PostMapping("/add")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Long> addUser(@RequestBody UserAddDTO userAddDTO) {
        // 1. 判断请求参数
        if (userAddDTO == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 2. 封装user参数
        User user = new User();
        BeanUtils.copyProperties(userAddDTO, user);
        // 加密
        String defaultPassword = "12345678";
        String encryptionPassword = userService.getEncryptionPassword(defaultPassword);
        user.setUserPassword(encryptionPassword);
        // 3. 执行添加操作
        boolean saveResult = userService.save(user);
        if (!saveResult) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "新增失败");
        }
        // 4. 返回userId
        return ResultUtils.success(user.getId());
    }

    /**
     * 根据id删除用户 (管理员)
     *
     * @param deleteRequest 删除参数
     * @return 删除结果
     */
    @ApiOperation(value = "根据 id 删除用户（管理员）")
    @PostMapping("/delete")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> deleteUser(@RequestBody DeleteRequest deleteRequest) {
        // 1. 判空
        ThrowUtils.throwIf((deleteRequest == null && deleteRequest.getId() <= 0), ErrorCode.PARAMS_ERROR);
        // 2. 删除用户
        Long userId = deleteRequest.getId();
        boolean deleteResult = userService.removeById(userId);
        if (!deleteResult) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "删除失败");
        }
        // 3. 返回结果
        return ResultUtils.success(true);
    }

    /**
     * 根据id获取用户 (不脱敏的完整用户信息) (管理员)
     * @param id 用户id
     * @return 用户信息
     */
    @ApiOperation(value = "根据 id 获取完整用户信息（管理员）")
    @GetMapping("/get")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<User> getUserById(Long id) {
        // 1. 判空
        ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        // 2. 获取用户
        User user = userService.getById(id);
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        }
        // 3. 返回结果
        return ResultUtils.success(user);
    }

    /**
     * 根据id获取用户 (查询脱敏后的用户信息)
     * @param id 用户id
     * @return 用户信息
     */
    @ApiOperation(value = "根据 id 获取脱敏后的用户信息")
    @GetMapping("/get/vo")
    public BaseResponse<UserVO> getUserVoById(Long id) {
        // 1. 判空
        ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        // 2. 获取用户
        User user = userService.getById(id);
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        }
        UserVO userVO = userService.getUserVO(user);
        // 3. 返回结果
        return ResultUtils.success(userVO);
    }

    /**
     * 更新用户信息 （管理员）
     *
     * @param userUpdateDTO 更新用户参数
     * @return 更新结果
     */
    @ApiOperation(value = "更新用户信息（管理员）")
    @PostMapping("/update")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> updateUser(@RequestBody UserUpdateDTO userUpdateDTO, HttpServletRequest request) {
        // 1. 判断请求参数
        if (userUpdateDTO == null || userUpdateDTO.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 当前登录用户既不是本人也不是管理员，则拦截
        User loginUser = userService.getLoginUser(request);
        if(!loginUser.getId().equals(userUpdateDTO.getId()) && !loginUser.getUserRole().equals(UserConstant.ADMIN_ROLE)){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        // 2. 封装更新user参数
        UpdateWrapper<User> userUpdateWrapper = userService.getUserUpdateWrapper(userUpdateDTO, loginUser);
        // 3. 执行修改操作
        boolean updateResult = userService.update(userUpdateWrapper);
        if (!updateResult) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新失败");
        }
        // 4. 如果修改了密码，删除登录态，重定向到登陆页面重新登陆
        String userPassword = userUpdateDTO.getUserPassword();
        String newPassword = userUpdateDTO.getNewPassword();
        String checkPassword = userUpdateDTO.getCheckPassword();
        if(!StrUtil.hasBlank(userPassword, newPassword, checkPassword)){
            userService.userLogout(request);
        }
        // 5. 返回userId
        return ResultUtils.success(true);
    }

    /**
     * 更新用户信息 （普通用户）
     *
     * @param userEditDTO 更新用户参数
     * @return 更新结果
     */
    @ApiOperation(value = "更新用户信息（普通用户）")
    @PostMapping("/edit")
    public BaseResponse<Boolean> editUser(@RequestBody UserEditDTO userEditDTO, HttpServletRequest request) {
        // 1. 判断请求参数
        if (userEditDTO == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 当前登录用户既不是本人也不是管理员，则拦截
        User loginUser = userService.getLoginUser(request);
        if(!loginUser.getId().equals(userEditDTO.getId()) && !loginUser.getUserRole().equals(UserConstant.ADMIN_ROLE)){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        // 2. 封装更新user参数
        UserUpdateDTO userUpdateDTO = new UserUpdateDTO();
        BeanUtils.copyProperties(userEditDTO, userUpdateDTO);
        // 设置登录用户 id
        if(userUpdateDTO.getId() == null){
            userUpdateDTO.setId(loginUser.getId());
        }
        UpdateWrapper<User> userUpdateWrapper = userService.getUserUpdateWrapper(userUpdateDTO, loginUser);
        // 3. 执行修改操作
        boolean updateResult = userService.update(userUpdateWrapper);
        if (!updateResult) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新失败");
        }
        // 4. 如果修改了密码，删除登录态，重定向到登陆页面重新登陆
        String userPassword = userUpdateDTO.getUserPassword();
        String newPassword = userUpdateDTO.getNewPassword();
        String checkPassword = userUpdateDTO.getCheckPassword();
        if(!StrUtil.hasBlank(userPassword, newPassword, checkPassword)){
            userService.userLogout(request);
        }
        // 5. 返回userId
        return ResultUtils.success(true);
    }

    /**
     * 获取分页后的用户列表（管理员）
     * @param userQueryDTO 查询参数
     * @return 分页后的用户列表
     */
    @ApiOperation(value = "分页获取完整的用户信息列表（管理员）")
    @PostMapping("/list/page/vo")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Page<UserVO>> listUserVoByPage(@RequestBody UserQueryDTO userQueryDTO) {
        // 1. 判空
        ThrowUtils.throwIf(userQueryDTO == null, ErrorCode.PARAMS_ERROR);
        // 2. 获取请求参数
        long current = userQueryDTO.getCurrent();
        long pageSize = userQueryDTO.getPageSize();
        QueryWrapper<User> userQueryWrapper = userService.getQueryWrapper(userQueryDTO);
        // 3. 获取分页后的用户集合
        Page<User> userPage = userService.page(new Page<>(current, pageSize), userQueryWrapper);
        // 4. 对用户集合脱敏
        Page<UserVO> userVOPage = new Page<>(current, pageSize, userPage.getTotal());
        List<UserVO> userVOList = userService.getUserVOList(userPage.getRecords());
        userVOPage.setRecords(userVOList);
        // 5. 返回结果
        return ResultUtils.success(userVOPage);
    }


}
